package cn.flying.cloud.tool.code.controller;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.flying.cloud.base.common.vo.Rt;
import cn.flying.cloud.tool.code.service.GenerateCodeService;
import cn.flying.cloud.tool.vo.GenerateConfig;
import cn.flying.cloud.tool.vo.TableInfoVO;

/**
 * 自动生成代码 前端控制器
 *
 * @author: admin
 * @date: 2024年04月07日 12:56
 * @version: 1.0
 */
@RestController
@RequestMapping("/tool/code")
public class GenerateController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private GenerateCodeService generateCodeService;

    /**
     * 查询表信息
     *
     * @param id
     * @return
     */
    @GetMapping("getTableList/{id}")
    public Rt getTableList(@PathVariable Long id) throws Exception {
        List<TableInfoVO> list = generateCodeService.getTableList(id);
        return Rt.success(list);
    }

    /**
     * 创建代码
     *
     * @param config
     * @return
     */
    @PostMapping("generate")
    public Rt generate(@RequestBody GenerateConfig config) {
        // 先将原来生成的代码目录删除
        File folder = new File(System.getProperty("user.dir") + "/src/");
        try {
            if (folder.exists()) {
                Files.walk(folder.toPath())
                        .sorted((p1, p2) -> p2.compareTo(p1))
                        .map(Path::toFile)
                        .forEach(File::delete);
                logger.info("目录删除成功！");
            }
        } catch (IOException e) {
            logger.error("目录删除失败 -->", e);
        }

        //生成代码
        if ("MB".equals(config.getCodeStyle())) {
            try {
                generateCodeService.generateMbStyleCode(config);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            generateCodeService.generateMpStyleCode(config);
        }
        //读取文件
        Map<String, String> map = generateCodeService.readFile(config);
        return Rt.success(map);
    }

    /**
     * 下载代码
     *
     * @param response
     * @throws Exception
     */
    @GetMapping("download")
    public void download(HttpServletResponse response) throws Exception {
//        String zipFilePath = System.getProperty("user.dir") + "/src.zip";

        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=\"src.zip\"");
        try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
            File srcDir = new File(System.getProperty("user.dir"), "src");
            zipDirectory(srcDir, zos, "");
        }

    }

    private void zipDirectory(File sourceDir, ZipOutputStream zos, String parentPath) throws IOException {
        for (File file : Objects.requireNonNull(sourceDir.listFiles())) {
            String entryName = parentPath + file.getName();
            if (file.isDirectory()) {
                entryName += File.separator; // 确保目录以分隔符结尾
                zos.putNextEntry(new ZipEntry(entryName));
                zipDirectory(file, zos, entryName);
            } else {
                zos.putNextEntry(new ZipEntry(entryName));
                try (FileInputStream fis = new FileInputStream(file)) {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = fis.read(buffer)) > 0) {
                        zos.write(buffer, 0, len);
                    }
                }
            }
            zos.closeEntry();
        }
    }

}
